package es.mgil.whoWantsToBeAMillonaire.runnables;

import android.os.Message;
import android.widget.TextView;
import es.mgil.whoWantsToBeAMillonaire.activities.Play;
import es.mgil.whoWantsToBeAMillonaire.handlers.ResponseProgressBarHandler;
import es.mgil.whoWantsToBeAMillonaire.util.PreferencesKeys;

public class ResponseProgressBarRunnable implements Runnable {
	public static final int RESPONSE_PROGRESS_BAR_UPDATE = 0;
	public static final int RESPONSE_PROGRESS_BAR_TIMEOUT = 1;
	public static final int RESPONSE_PROGRESS_BAR_CORRECT_NEXT = 2;
	public static final int RESPONSE_PROGRESS_BAR_CORRECT_END = 3;
	public static final int RESPONSE_PROGRESS_BAR_FAIL = 4;

	private static final int STATE_PREPARED = -1;
	private static final int STATE_LOOPING = 0;
	private static final int STATE_ANSWERED = 1;
	private static final int STATE_CANCELLED = 2;
	private static final int STATE_ASKING_EXIT = 3;
	private static final int STATE_TIMEOUT = 4;

	private Play play;
	private ResponseProgressBarHandler handler;

	private int currentState = Integer.MIN_VALUE;

	public ResponseProgressBarRunnable(Play play) {
		this.play = play;
		this.handler = new ResponseProgressBarHandler(play);
	}

	@Override
	public void run() {
		loop: while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}

			switch (currentState) {
			case STATE_PREPARED:
				break loop;
			case STATE_TIMEOUT:
				break loop;
			case STATE_CANCELLED:
				break loop;
			case STATE_ASKING_EXIT:
				continue;
			case STATE_ANSWERED:
				checkSelectedAnswer();
				break loop;
			case STATE_LOOPING:
				if (play.progressBar.getProgress() == play.progressBar.getMax()) {
					// when looping arrives to the end, show a message to
					// the user and end the thread
					timeout();
					handler.sendMessage(Message.obtain(handler,
							RESPONSE_PROGRESS_BAR_TIMEOUT));
					break loop;
				} else {
					// if looping, update the progress bar
					handler.sendMessage(Message.obtain(handler,
							RESPONSE_PROGRESS_BAR_UPDATE));
				}
				break;
			}
		}
	}

	/**
	 * Start the looping. The thread starts running and the progress bar starts
	 * its progress. Only do it if current state is PREPARED or CANCELLED
	 */
	public void startLooping() {
		int state = play.preferences.getInt(
				PreferencesKeys.PREFERENCES_PROGRESS_STATE, STATE_PREPARED);
		if (state == STATE_PREPARED || state == STATE_CANCELLED) {
			setCurrentState(STATE_LOOPING);
			play.progressBar.setProgress(play.preferences.getInt(
					PreferencesKeys.PREFERENCES_PROGRESS_BAR_PROGRESS, 0));

			new Thread(this).start();
		}
	}

	/**
	 * Continue the looping. The thread will continue running
	 */
	public void continueLooping() {
		setCurrentState(STATE_PREPARED);
		startLooping();
	}

	/**
	 * Stop the looping. An answer is selected, so the thread should stop
	 * running and check the selected answer
	 */
	public void answered() {
		setCurrentState(STATE_ANSWERED);
		play.editor.remove(PreferencesKeys.PREFERENCES_PROGRESS_BAR_PROGRESS);
		play.editor.commit();
	}

	/**
	 * Pause the looping. When ask if exit, the thread is still running, but it
	 * doesn't nothing while no option is chosen. When user choose an option, it
	 * will be finally stopped or restarted
	 */
	public void askingExit() {
		setCurrentState(STATE_ASKING_EXIT);
	}

	/**
	 * Stop the looping. Stop running the thread for one of the following
	 * reasons: onPause method is executed in the activity or user choose stop
	 * playing. Only do it if current state is not ANSWERED, due to it's not
	 * necessary to do that cause it's already stopped
	 */
	public void cancelLopping() {
		int state = play.preferences.getInt(
				PreferencesKeys.PREFERENCES_PROGRESS_STATE, STATE_PREPARED);
		if (state == STATE_ANSWERED) {
			return;
		}
		setCurrentState(STATE_CANCELLED);
	}

	/**
	 * Stop the looping. The progress bar has arrived to its maximum value, so
	 * it's considered that the question is not answered and the thread will be
	 * stopped
	 */
	public void timeout() {
		setCurrentState(STATE_TIMEOUT);
	}

	/**
	 * Thread is prepared to be start. Will not be set prepared when current
	 * state is ANSWERED or ASKING EXIT, cause in first case we answered current
	 * question yet, and in second case we're still playing current question
	 */
	public void noState() {
		int state = play.preferences.getInt(
				PreferencesKeys.PREFERENCES_PROGRESS_STATE, STATE_PREPARED);
		if (state == STATE_ANSWERED || state == STATE_ASKING_EXIT) {
			return;
		}
		setCurrentState(STATE_PREPARED);
		play.editor.remove(PreferencesKeys.PREFERENCES_PROGRESS_STATE);
		play.editor.commit();
	}

	/**
	 * Store given current state in the preferences
	 */
	private void setCurrentState(int state) {
		currentState = state;
		play.editor.putInt(PreferencesKeys.PREFERENCES_PROGRESS_STATE, state);
		play.editor.commit();
	}

	/**
	 * Once an answer is selected, we need to treat it
	 */
	private void checkSelectedAnswer() {
		// first get the solution for the current question
		String solution = play.getCurrentQuestion().getAnswerFromNumber(
				play.getCurrentQuestion().getRight());
		for (TextView textView : play.getTextViews()) {
			if (textView.getText().toString().contains(solution)) {
				play.editor.putInt(String.valueOf(textView.getId())
						+ PreferencesKeys.PREFERENCES_COLOR,
						Play.STYLE_COLOR_RIGHT);
			}
		}

		// check if selected answer is right or not
		boolean isRight = false;
		int selAnswerId = play.preferences.getInt(
				PreferencesKeys.PREFERENCES_SELECTED_ANSWER, -1);
		TextView selAnswer = (TextView) play.findViewById(selAnswerId);
		if (selAnswer.getText().toString().contains(solution)) {
			isRight = true;
		} else {
			isRight = false;
			play.editor.putInt(String.valueOf(selAnswer.getId())
					+ PreferencesKeys.PREFERENCES_COLOR, Play.STYLE_COLOR_FAIL);
		}
		play.editor.commit();

		if (isRight) {
			// if it's right, notify the user about that and...
			if (play.preferences.getInt(
					PreferencesKeys.PREFERENCES_QUESTION_NUMBER, 1) != play
					.getQuestions().size()) {
				// ... ask user about next question if there are more
				// questions
				handler.sendMessage(Message.obtain(handler,
						RESPONSE_PROGRESS_BAR_CORRECT_NEXT));
			} else {
				// ... user wins the game, so notify it to him
				handler.sendMessage(Message.obtain(handler,
						RESPONSE_PROGRESS_BAR_CORRECT_END));
			}
		} else {
			// if it's not right, notify the user too
			handler.sendMessage(Message.obtain(handler,
					RESPONSE_PROGRESS_BAR_FAIL));
		}
	}
}
